home *** CD-ROM | disk | FTP | other *** search
/ NeXTSTEP 3.3 (Developer)…68k, x86, SPARC, PA-RISC] / NeXTSTEP 3.3 Dev Intel.iso / NextDeveloper / Source / GNU / cc / cp-xref.c < prev    next >
C/C++ Source or Header  |  1993-10-08  |  18KB  |  826 lines

  1. /* Code for handling XREF output from GNU C++.
  2.    Copyright (C) 1992, 1993 Free Software Foundation, Inc.
  3.    Contributed by Michael Tiemann (tiemann@cygnus.com)
  4.  
  5. This file is part of GNU CC.
  6.  
  7. GNU CC is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2, or (at your option)
  10. any later version.
  11.  
  12. GNU CC is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. GNU General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with GNU CC; see the file COPYING.  If not, write to
  19. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  20.  
  21.  
  22. #include "config.h"
  23. #include "tree.h"
  24. #include <stdio.h>
  25. #include "cp-tree.h"
  26. #include "input.h"
  27.  
  28. #include <ctype.h>
  29.  
  30. extern char *getpwd ();
  31.  
  32. extern char *index ();
  33. extern char *rindex ();
  34.  
  35. /* The character(s) used to join a directory specification (obtained with
  36.    getwd or equivalent) with a non-absolute file name.  */
  37.  
  38. #ifndef FILE_NAME_JOINER
  39. #define FILE_NAME_JOINER "/"
  40. #endif
  41.  
  42. /* Nonzero if NAME as a file name is absolute.  */
  43. #ifndef FILE_NAME_ABSOLUTE_P
  44. #define FILE_NAME_ABSOLUTE_P(NAME) (NAME[0] == '/')
  45. #endif
  46.  
  47. /* For cross referencing.  */
  48.  
  49. int flag_gnu_xref;
  50.  
  51. /************************************************************************/
  52. /*                                    */
  53. /*    Common definitions                        */
  54. /*                                    */
  55. /************************************************************************/
  56.  
  57. #ifndef TRUE
  58. #define TRUE 1
  59. #endif
  60. #ifndef FALSE
  61. #define FALSE 0
  62. #endif
  63. #ifndef NULL
  64. #define NULL 0
  65. #endif
  66.  
  67. #define PALLOC(typ) ((typ *) calloc(1,sizeof(typ)))
  68.  
  69.  
  70. /* Return a malloc'd copy of STR.  */
  71. #define SALLOC(str) \
  72.  ((char *) ((str) == NULL ? NULL    \
  73.         : (char *) strcpy ((char *) malloc (strlen ((str)) + 1), (str))))
  74. #define SFREE(str) (str != NULL && (free(str),0))
  75.  
  76. #define STREQL(s1,s2) (strcmp((s1),(s2)) == 0)
  77. #define STRNEQ(s1,s2) (strcmp((s1),(s2)) != 0)
  78. #define STRLSS(s1,s2) (strcmp((s1),(s2)) < 0)
  79. #define STRLEQ(s1,s2) (strcmp((s1),(s2)) <= 0)
  80. #define STRGTR(s1,s2) (strcmp((s1),(s2)) > 0)
  81. #define STRGEQ(s1,s2) (strcmp((s1),(s2)) >= 0)
  82.  
  83. /************************************************************************/
  84. /*                                    */
  85. /*    Type definitions                        */
  86. /*                                    */
  87. /************************************************************************/
  88.  
  89.  
  90. typedef struct _XREF_FILE *    XREF_FILE;
  91. typedef struct _XREF_SCOPE *    XREF_SCOPE;
  92.  
  93. typedef struct _XREF_FILE
  94. {
  95.   char *name;
  96.   char *outname;
  97.   XREF_FILE next;
  98. } XREF_FILE_INFO;
  99.  
  100. typedef struct _XREF_SCOPE
  101. {
  102.   int gid;
  103.   int lid;
  104.   XREF_FILE file;
  105.   int start;
  106.   XREF_SCOPE outer;
  107. } XREF_SCOPE_INFO;
  108.  
  109. /************************************************************************/
  110. /*                                    */
  111. /*    Local storage                            */
  112. /*                                    */
  113. /************************************************************************/
  114.  
  115. static    char        doing_xref = 0;
  116. static    FILE *        xref_file = NULL;
  117. static    char        xref_name[1024];
  118. static    XREF_FILE    all_files = NULL;
  119. static    char *        wd_name = NULL;
  120. static    XREF_SCOPE    cur_scope = NULL;
  121. static    int     scope_ctr = 0;
  122. static    XREF_FILE    last_file = NULL;
  123. static    tree        last_fndecl = NULL;
  124.  
  125. /************************************************************************/
  126. /*                                    */
  127. /*    Forward definitions                        */
  128. /*                                    */
  129. /************************************************************************/
  130.  
  131. extern    void        GNU_xref_begin();
  132. extern    void        GNU_xref_end();
  133. extern    void        GNU_xref_file();
  134. extern    void        GNU_xref_start_scope();
  135. extern    void        GNU_xref_end_scope();
  136. extern    void        GNU_xref_ref();
  137. extern    void        GNU_xref_decl();
  138. extern    void        GNU_xref_call();
  139. extern    void        GNU_xref_function();
  140. extern    void        GNU_xref_assign();
  141. extern    void        GNU_xref_hier();
  142. extern    void        GNU_xref_member();
  143.  
  144. static    void        gen_assign();
  145. static    XREF_FILE    find_file();
  146. static    char *        filename();
  147. static    char *        fctname();
  148. static    char *        declname();
  149. static    void        simplify_type();
  150. static    char *        fixname();
  151. static    void        open_xref_file();
  152.  
  153. extern    char *        type_as_string();
  154.  
  155. /* Start cross referencing.  FILE is the name of the file we xref.  */
  156.  
  157. void
  158. GNU_xref_begin (file)
  159.    char *file;
  160. {
  161.   doing_xref = 1;
  162.  
  163.   if (file != NULL && STRNEQ (file,"-"))
  164.     {
  165.       open_xref_file(file);
  166.       GNU_xref_file(file);
  167.     }
  168. }
  169.  
  170. /* Finish cross-referencing.  ERRCNT is the number of errors
  171.    we encountered.  */
  172.  
  173. void
  174. GNU_xref_end (ect)
  175.    int ect;
  176. {
  177.   XREF_FILE xf;
  178.  
  179.   if (!doing_xref) return;
  180.  
  181.   xf = find_file (input_filename);
  182.   if (xf == NULL) return;
  183.  
  184.   while (cur_scope != NULL)
  185.     GNU_xref_end_scope(cur_scope->gid,0,0,0,0);
  186.  
  187.   doing_xref = 0;
  188.  
  189.   if (xref_file == NULL) return;
  190.  
  191.   fclose (xref_file);
  192.  
  193.   xref_file = NULL;
  194.   all_files = NULL;
  195.  
  196.   if (ect > 0) unlink (xref_name);
  197. }
  198.  
  199. /* Write out xref for file named NAME.  */
  200.  
  201. void
  202. GNU_xref_file (name)
  203.    char *name;
  204. {
  205.   XREF_FILE xf;
  206.  
  207.   if (!doing_xref || name == NULL) return;
  208.  
  209.   if (xref_file == NULL)
  210.     {
  211.       open_xref_file (name);
  212.       if (!doing_xref) return;
  213.     }
  214.  
  215.   if (all_files == NULL)
  216.     fprintf(xref_file,"SCP * 0 0 0 0 RESET\n");
  217.  
  218.   xf = find_file (name);
  219.   if (xf != NULL) return;
  220.  
  221.   xf = PALLOC (XREF_FILE_INFO);
  222.   xf->name = SALLOC (name);
  223.   xf->next = all_files;
  224.   all_files = xf;
  225.  
  226.   if (wd_name == NULL)
  227.     wd_name = getpwd ();
  228.  
  229.   if (FILE_NAME_ABSOLUTE_P (name) || ! wd_name)
  230.     xf->outname = xf->name;
  231.   else
  232.     {
  233.       char *nmbuf
  234.     = (char *) malloc (strlen (wd_name) + strlen (FILE_NAME_JOINER)
  235.                + strlen (name) + 1);
  236.       sprintf (nmbuf, "%s%s%s", wd_name, FILE_NAME_JOINER, name);
  237.       name = nmbuf;
  238.       xf->outname = nmbuf;
  239.     }
  240.  
  241.   fprintf (xref_file, "FIL %s %s 0\n", name, wd_name);
  242.  
  243.   filename (xf);
  244.   fctname (NULL);
  245. }
  246.  
  247. /* Start a scope identified at level ID.  */
  248.  
  249. void
  250. GNU_xref_start_scope (id)
  251.    HOST_WIDE_INT id;
  252. {
  253.   XREF_SCOPE xs;
  254.   XREF_FILE xf;
  255.  
  256.   if (!doing_xref) return;
  257.   xf = find_file (input_filename);
  258.  
  259.   xs = PALLOC (XREF_SCOPE_INFO);
  260.   xs->file = xf;
  261.   xs->start = lineno;
  262.   if (xs->start <= 0) xs->start = 1;
  263.   xs->gid = id;
  264.   xs->lid = ++scope_ctr;
  265.   xs->outer = cur_scope;
  266.   cur_scope = xs;
  267. }
  268.  
  269. /* Finish a scope at level ID.
  270.    INID is ???
  271.    PRM is ???
  272.    KEEP is nonzero iff this scope is retained (nonzero if it's
  273.    a compiler-generated invisible scope).
  274.    TRNS is ???  */
  275.  
  276. void
  277. GNU_xref_end_scope (id,inid,prm,keep,trns)
  278.    HOST_WIDE_INT id;
  279.    HOST_WIDE_INT inid;
  280.    int prm,keep,trns;
  281. {
  282.   XREF_FILE xf;
  283.   XREF_SCOPE xs,lxs,oxs;
  284.   char *stype;
  285.  
  286.   if (!doing_xref) return;
  287.   xf = find_file (input_filename);
  288.   if (xf == NULL) return;
  289.  
  290.   lxs = NULL;
  291.   for (xs = cur_scope; xs != NULL; xs = xs->outer)
  292.     {
  293.       if (xs->gid == id) break;
  294.       lxs = xs;
  295.     }
  296.   if (xs == NULL) return;
  297.  
  298.   if (inid != 0) {
  299.     for (oxs = cur_scope; oxs != NULL; oxs = oxs->outer) {
  300.       if (oxs->gid == inid) break;
  301.     }
  302.     if (oxs == NULL) return;
  303.     inid = oxs->lid;
  304.   }
  305.  
  306.   if (prm == 2) stype = "SUE";
  307.   else if (prm != 0) stype = "ARGS";
  308.   else if (keep == 2 || inid != 0) stype = "INTERN";
  309.   else stype = "EXTERN";
  310.  
  311.   fprintf (xref_file,"SCP %s %d %d %d %d %s\n",
  312.        filename (xf), xs->start, lineno,xs->lid, inid, stype);
  313.  
  314.   if (lxs == NULL) cur_scope = xs->outer;
  315.   else lxs->outer = xs->outer;
  316.  
  317.   free (xs);
  318. }
  319.  
  320. /* Output a reference to NAME in FNDECL.  */
  321.  
  322. void
  323. GNU_xref_ref (fndecl,name)
  324.    tree fndecl;
  325.    char *name;
  326. {
  327.   XREF_FILE xf;
  328.  
  329.   if (!doing_xref) return;
  330.   xf = find_file (input_filename);
  331.   if (xf == NULL) return;
  332.  
  333.   fprintf (xref_file, "REF %s %d %s %s\n",
  334.        filename (xf), lineno, fctname (fndecl), name);
  335. }
  336.  
  337. /* Output a reference to DECL in FNDECL.  */
  338.  
  339. void
  340. GNU_xref_decl (fndecl,decl)
  341.    tree fndecl;
  342.    tree decl;
  343. {
  344.   XREF_FILE xf,xf1;
  345.   char *cls;
  346.   char *name;
  347.   char buf[10240];
  348.   int uselin;
  349.  
  350.   if (!doing_xref) return;
  351.   xf = find_file (input_filename);
  352.   if (xf == NULL) return;
  353.  
  354.   uselin = FALSE;
  355.  
  356.   if (TREE_CODE (decl) == TYPE_DECL) cls = "TYPEDEF";
  357.   else if (TREE_CODE (decl) == FIELD_DECL) cls = "FIELD";
  358.   else if (TREE_CODE (decl) == VAR_DECL)
  359.     {
  360.       if (fndecl == NULL && TREE_STATIC(decl)
  361.       && TREE_READONLY(decl) && DECL_INITIAL(decl) != 0
  362.       && !TREE_PUBLIC(decl) && !DECL_EXTERNAL(decl)
  363.       && DECL_MODE(decl) != BLKmode) cls = "CONST";
  364.       else if (DECL_EXTERNAL(decl)) cls = "EXTERN";
  365.       else if (TREE_PUBLIC(decl)) cls = "EXTDEF";
  366.       else if (TREE_STATIC(decl)) cls = "STATIC";
  367.       else if (DECL_REGISTER(decl)) cls = "REGISTER";
  368.       else cls = "AUTO";
  369.     }
  370.   else if (TREE_CODE (decl) == PARM_DECL) cls = "PARAM";
  371.   else if (TREE_CODE (decl) == FIELD_DECL) cls = "FIELD";
  372.   else if (TREE_CODE (decl) == CONST_DECL) cls = "CONST";
  373.   else if (TREE_CODE (decl) == FUNCTION_DECL)
  374.     {
  375.       if (DECL_EXTERNAL (decl)) cls = "EXTERN";
  376.       else if (TREE_PUBLIC (decl)) cls = "EFUNCTION";
  377.       else cls = "SFUNCTION";
  378.     }
  379.   else if (TREE_CODE (decl) == LABEL_DECL) cls = "LABEL";
  380.   else if (TREE_CODE (decl) == UNION_TYPE)
  381.     {
  382.       cls = "UNIONID";
  383.       decl = TYPE_NAME (decl);
  384.       uselin = TRUE;
  385.     }
  386.   else if (TREE_CODE (decl) == RECORD_TYPE)
  387.     {
  388.       if (CLASSTYPE_DECLARED_CLASS (decl)) cls = "CLASSID";
  389.       else cls = "STRUCTID";
  390.       decl = TYPE_NAME (decl);
  391.       uselin = TRUE;
  392.     }
  393.   else if (TREE_CODE (decl) == ENUMERAL_TYPE)
  394.     {
  395.       cls = "ENUMID";
  396.       decl = TYPE_NAME (decl);
  397.       uselin = TRUE;
  398.     }
  399.   else cls = "UNKNOWN";
  400.  
  401.   if (decl == NULL || DECL_NAME (decl) == NULL) return;
  402.  
  403.   if (uselin && decl->decl.linenum > 0 && decl->decl.filename != NULL)
  404.     {
  405.       xf1 = find_file (decl->decl.filename);
  406.       if (xf1 != NULL)
  407.     {
  408.       lineno = decl->decl.linenum;
  409.       xf = xf1;
  410.     }
  411.     }
  412.  
  413.   if (DECL_ASSEMBLER_NAME (decl))
  414.     name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
  415.   else
  416.     name = IDENTIFIER_POINTER (DECL_NAME (decl));
  417.  
  418.   strcpy (buf, type_as_string (TREE_TYPE (decl), 0));
  419.   simplify_type (buf);
  420.  
  421.   fprintf (xref_file, "DCL %s %d %s %d %s %s %s\n",
  422.        filename(xf), lineno, name,
  423.        (cur_scope != NULL ? cur_scope->lid : 0),
  424.        cls, fctname(fndecl), buf);
  425.  
  426.   if (STREQL (cls, "STRUCTID") || STREQL (cls, "UNIONID"))
  427.     {
  428.       cls = "CLASSID";
  429.       fprintf (xref_file, "DCL %s %d %s %d %s %s %s\n",
  430.            filename(xf), lineno,name,
  431.            (cur_scope != NULL ? cur_scope->lid : 0),
  432.            cls, fctname(fndecl), buf);
  433.     }
  434. }
  435.  
  436. /* Output a reference to a call to NAME in FNDECL.  */
  437.  
  438. void
  439. GNU_xref_call (fndecl, name)
  440.    tree fndecl;
  441.    char *name;
  442. {
  443.   XREF_FILE xf;
  444.   char buf[1024];
  445.   char *s;
  446.  
  447.   if (!doing_xref) return;
  448.   xf = find_file (input_filename);
  449.   if (xf == NULL) return;
  450.   name = fixname (name, buf);
  451.  
  452.   for (s = name; *s != 0; ++s)
  453.     if (*s == '_' && s[1] == '_') break;
  454.   if (*s != 0) GNU_xref_ref (fndecl, name);
  455.  
  456.   fprintf (xref_file, "CAL %s %d %s %s\n",
  457.        filename (xf), lineno, name, fctname (fndecl));
  458. }
  459.  
  460. /* Output cross-reference info about FNDECL.  If non-NULL,
  461.    ARGS are the arguments for the function (i.e., before the FUNCTION_DECL
  462.    has been fully built).  */
  463.  
  464. void
  465. GNU_xref_function (fndecl, args)
  466.    tree fndecl;
  467.    tree args;
  468. {
  469.   XREF_FILE xf;
  470.   int ct;
  471.   char buf[1024];
  472.  
  473.   if (!doing_xref) return;
  474.   xf = find_file (input_filename);
  475.   if (xf == NULL) return;
  476.  
  477.   ct = 0;
  478.   buf[0] = 0;
  479.   if (args == NULL) args = DECL_ARGUMENTS (fndecl);
  480.  
  481.   GNU_xref_decl (NULL, fndecl);
  482.  
  483.   for ( ; args != NULL; args = TREE_CHAIN (args))
  484.     {
  485.       GNU_xref_decl (fndecl,args);
  486.       if (ct != 0) strcat (buf,",");
  487.       strcat (buf, declname (args));
  488.       ++ct;
  489.     }
  490.  
  491.   fprintf (xref_file, "PRC %s %d %s %d %d %s\n",
  492.        filename(xf), lineno, declname(fndecl),
  493.        (cur_scope != NULL ? cur_scope->lid : 0),
  494.        ct, buf);
  495. }
  496.  
  497. /* Output cross-reference info about an assignment to NAME.  */
  498.  
  499. void
  500. GNU_xref_assign(name)
  501.    tree name;
  502. {
  503.   XREF_FILE xf;
  504.  
  505.   if (!doing_xref) return;
  506.   xf = find_file(input_filename);
  507.   if (xf == NULL) return;
  508.  
  509.   gen_assign(xf, name);
  510. }
  511.  
  512. static void
  513. gen_assign(xf, name)
  514.    XREF_FILE xf;
  515.    tree name;
  516. {
  517.   char *s;
  518.  
  519.   s = NULL;
  520.  
  521.   switch (TREE_CODE (name))
  522.     {
  523.     case IDENTIFIER_NODE :
  524.       s = IDENTIFIER_POINTER(name);
  525.       break;
  526.     case VAR_DECL :
  527.       s = declname(name);
  528.       break;
  529.     case COMPONENT_REF :
  530.       gen_assign(xf, TREE_OPERAND(name, 0));
  531.       gen_assign(xf, TREE_OPERAND(name, 1));
  532.       break;
  533.     case INDIRECT_REF :
  534.     case OFFSET_REF :
  535.     case ARRAY_REF :
  536.     case BUFFER_REF :
  537.       gen_assign(xf, TREE_OPERAND(name, 0));
  538.       break;
  539.     case COMPOUND_EXPR :
  540.       gen_assign(xf, TREE_OPERAND(name, 1));
  541.       break;
  542.       default :
  543.       break;
  544.     }
  545.  
  546.   if (s != NULL)
  547.     fprintf(xref_file, "ASG %s %d %s\n", filename(xf), lineno, s);
  548. }
  549.  
  550. /* Output cross-reference info about a class hierarchy.
  551.    CLS is the class type of interest.  BASE is a baseclass
  552.    for CLS.  PUB and VIRT give the visibility info about
  553.    the class derivation.  FRND is nonzero iff BASE is a friend
  554.    of CLS.
  555.  
  556.    ??? Needs to handle nested classes.  */
  557. void
  558. GNU_xref_hier(cls, base, pub, virt, frnd)
  559.    char *cls;
  560.    char *base;
  561.    int pub;
  562.    int virt;
  563.    int frnd;
  564. {
  565.   XREF_FILE xf;
  566.  
  567.   if (!doing_xref) return;
  568.   xf = find_file(input_filename);
  569.   if (xf == NULL) return;
  570.  
  571.   fprintf(xref_file, "HIE %s %d %s %s %d %d %d\n",
  572.       filename(xf), lineno, cls, base, pub, virt, frnd);
  573. }
  574.  
  575. /* Output cross-reference info about class members.  CLS
  576.    is the containing type; FLD is the class member.  */
  577.  
  578. void
  579. GNU_xref_member(cls, fld)
  580.    tree cls;
  581.    tree fld;
  582. {
  583.   XREF_FILE xf;
  584.   char *prot;
  585.   int confg, pure;
  586.   char *d;
  587.   int i;
  588.   char buf[1024], bufa[1024];
  589.  
  590.   if (!doing_xref) return;
  591.   xf = find_file(fld->decl.filename);
  592.   if (xf == NULL) return;
  593.  
  594.   if (TREE_PRIVATE (fld)) prot = "PRIVATE";
  595.   else if (TREE_PROTECTED(fld)) prot = "PROTECTED";
  596.   else prot = "PUBLIC";
  597.  
  598.   confg = 0;
  599.   if (TREE_CODE (fld) == FUNCTION_DECL && DECL_CONST_MEMFUNC_P(fld))
  600.     confg = 1;
  601.   else if (TREE_CODE (fld) == CONST_DECL)
  602.     confg = 1;
  603.  
  604.   pure = 0;
  605.   if (TREE_CODE (fld) == FUNCTION_DECL && DECL_ABSTRACT_VIRTUAL_P(fld))
  606.     pure = 1;
  607.  
  608.   d = IDENTIFIER_POINTER(cls);
  609.   sprintf(buf, "%d%s", strlen(d), d);
  610.   i = strlen(buf);
  611.   strcpy(bufa, declname(fld));
  612.  
  613. #ifdef XREF_SHORT_MEMBER_NAMES
  614.   for (p = &bufa[1]; *p != 0; ++p)
  615.     {
  616.       if (p[0] == '_' && p[1] == '_' && p[2] >= '0' && p[2] <= '9') {
  617.     if (strncmp(&p[2], buf, i) == 0) *p = 0;
  618.     break;
  619.       }
  620.       else if (p[0] == '_' && p[1] == '_' && p[2] == 'C' && p[3] >= '0' && p[3] <= '9') {
  621.     if (strncmp(&p[3], buf, i) == 0) *p = 0;
  622.     break;
  623.       }
  624.     }
  625. #endif
  626.  
  627.   fprintf(xref_file, "MEM %s %d %s %s %s %d %d %d %d %d %d %d\n",
  628.       filename(xf), fld->decl.linenum, d,  bufa,  prot,
  629.       (TREE_CODE (fld) == FUNCTION_DECL ? 0 : 1),
  630.       (DECL_INLINE (fld) ? 1 : 0),
  631.       (DECL_FRIEND_P(fld) ? 1 : 0),
  632.       (DECL_VINDEX(fld) ? 1 : 0),
  633.       (TREE_STATIC(fld) ? 1 : 0),
  634.       pure, confg);
  635. }
  636.  
  637. /* Find file entry given name.  */
  638.  
  639. static XREF_FILE
  640. find_file(name)
  641.    char *name;
  642. {
  643.   XREF_FILE xf;
  644.  
  645.   for (xf = all_files; xf != NULL; xf = xf->next) {
  646.     if (STREQL(name, xf->name)) break;
  647.   }
  648.  
  649.   return xf;
  650. }
  651.  
  652. /* Return filename for output purposes.  */
  653.  
  654. static char *
  655. filename(xf)
  656.    XREF_FILE xf;
  657. {
  658.   if (xf == NULL) {
  659.     last_file = NULL;
  660.     return "*";
  661.   }
  662.  
  663.   if (last_file == xf) return "*";
  664.  
  665.   last_file = xf;
  666.  
  667.   return xf->outname;
  668. }
  669.  
  670. /* Return function name for output purposes.  */
  671.  
  672. static char *
  673. fctname(fndecl)
  674.    tree fndecl;
  675. {
  676.   static char fctbuf[1024];
  677.   char *s;
  678.  
  679.   if (fndecl == NULL && last_fndecl == NULL) return "*";
  680.  
  681.   if (fndecl == NULL)
  682.     {
  683.       last_fndecl = NULL;
  684.       return "*TOP*";
  685.     }
  686.  
  687.   if (fndecl == last_fndecl) return "*";
  688.  
  689.   last_fndecl = fndecl;
  690.  
  691.   s = declname(fndecl);
  692.   s = fixname(s, fctbuf);
  693.  
  694.   return s;
  695. }
  696.  
  697. /* Return decl name for output purposes.  */
  698.  
  699. static char *
  700. declname(dcl)
  701.    tree dcl;
  702. {
  703.   if (DECL_NAME (dcl) == NULL) return "?";
  704.  
  705.   if (DECL_ASSEMBLER_NAME (dcl))
  706.     return IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (dcl));
  707.   else
  708.     return IDENTIFIER_POINTER (DECL_NAME (dcl));
  709. }
  710.  
  711. /* Simplify a type string by removing unneeded parenthesis.  */
  712.  
  713. static void
  714. simplify_type(typ)
  715.    char *typ;
  716. {
  717.   char *s;
  718.   int lvl, i;
  719.  
  720.   i = strlen(typ);
  721.   while (i > 0 && isspace(typ[i-1])) typ[--i] = 0;
  722.  
  723.   if (i > 7 && STREQL(&typ[i-5], "const"))
  724.     {
  725.       typ[i-5] = 0;
  726.       i -= 5;
  727.     }
  728.  
  729.   if (typ[i-1] != ')') return;
  730.  
  731.   s = &typ[i-2];
  732.   lvl = 1;
  733.   while (*s != 0) {
  734.     if (*s == ')') ++lvl;
  735.     else if (*s == '(')
  736.       {
  737.     --lvl;
  738.     if (lvl == 0)
  739.       {
  740.         s[1] = ')';
  741.         s[2] = 0;
  742.         break;
  743.       }
  744.       }
  745.     --s;
  746.   }
  747.  
  748.   if (*s != 0 && s[-1] == ')')
  749.     {
  750.       --s;
  751.       --s;
  752.       if (*s == '(') s[2] = 0;
  753.       else if (*s == ':') {
  754.     while (*s != '(') --s;
  755.     s[1] = ')';
  756.     s[2] = 0;
  757.       }
  758.     }
  759. }
  760.  
  761. /* Fixup a function name (take care of embedded spaces).  */
  762.  
  763. static char *
  764. fixname(nam, buf)
  765.    char *nam;
  766.    char *buf;
  767. {
  768.   char *s, *t;
  769.   int fg;
  770.  
  771.   s = nam;
  772.   t = buf;
  773.   fg = 0;
  774.  
  775.   while (*s != 0)
  776.     {
  777.       if (*s == ' ')
  778.     {
  779.       *t++ = '\36';
  780.       ++fg;
  781.     }
  782.       else *t++ = *s;
  783.       ++s;
  784.     }
  785.   *t = 0;
  786.  
  787.   if (fg == 0) return nam;
  788.  
  789.   return buf;
  790. }
  791.  
  792. /* Open file for xrefing.  */
  793.  
  794. static void
  795. open_xref_file(file)
  796.    char *file;
  797. {
  798.   char *s, *t;
  799.  
  800. #ifdef XREF_FILE_NAME
  801.   XREF_FILE_NAME (xref_name, file);
  802. #else
  803.   s = rindex (file, '/');
  804.   if (s == NULL)
  805.     sprintf (xref_name, ".%s.gxref", file);
  806.   else
  807.     {
  808.       ++s;
  809.       strcpy (xref_name, file);
  810.       t = rindex (xref_name, '/');
  811.       ++t;
  812.       *t++ = '.';
  813.       strcpy (t, s);
  814.       strcat (t, ".gxref");
  815.     }
  816. #endif /* no XREF_FILE_NAME */
  817.  
  818.   xref_file = fopen(xref_name, "w");
  819.  
  820.   if (xref_file == NULL)
  821.     {
  822.       error("Can't create cross-reference file `%s'", xref_name);
  823.       doing_xref = 0;
  824.     }
  825. }
  826.